package cn.taobaoke.restful.service;

import cn.taobaoke.restful.domain.*;
import cn.taobaoke.restful.util.Constants;
import cn.taobaoke.restful.util.GsonUtil;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.val;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author yangzuo
 * @since 2017-03-25
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class OrderService {

    public static final String ACTION = "type";
    public static final String INSERT = "1";
    public static final String UPDATE = "2";
    public static final String ENTITY = "OrderEntity";

    /**
     * 存储订单
     *
     * @param orderEntity
     * @return
     */
    public Map<String, Object> storeOrder(final OrderEntity orderEntity, final Long domainId, final String domain) {

        Map<String, Object> result = new HashMap<>();
        result.put(ACTION, INSERT);

        String postfix = orderEntity.getMediaId() + "_" + orderEntity.getAdPositionId();
        val pidEntityOpt = pidRepository.findTopByDomainIdAndPidEndsWith(domainId, postfix);
        if (pidEntityOpt.isPresent()) {
            orderEntity.setPid(pidEntityOpt.get().getPid());
        }

        val entityOpt = orderV2Repository.findByOrderNumber(orderEntity.getOrderNumber(), domain);
        if (entityOpt.isPresent()) { // 根据订单号查询订单, 若订单已经存在, 则更新订单内容
            val entity = entityOpt.get();
            orderEntity.setId(entity.getId());
            orderEntity.setPid(entity.getPid());
            result.put(ACTION, UPDATE);
        }

        calculateOrderIncomeAndAgentId(orderEntity, domainId);
        result.put(ENTITY, orderV2Repository.save(orderEntity, domain));
        return result;
    }

    public Map<String, Integer> batchStoreOrder(final List<OrderEntity> orderEntityList, final Long domainId, final String domain) {
        List<OrderEntity> insertList = new ArrayList<>();
        List<OrderEntity> updateList = new ArrayList<>();


        for (OrderEntity orderEntity : orderEntityList) {
            String postfix = orderEntity.getMediaId() + "_" + orderEntity.getAdPositionId();
            val pidEntityOpt = pidRepository.findTopByDomainIdAndPidEndsWith(domainId, postfix);
            if (pidEntityOpt.isPresent()) {
                orderEntity.setPid(pidEntityOpt.get().getPid());
            }

            val entityOpt = orderV2Repository.findByOrderNumber(orderEntity.getOrderNumber(), domain);
            if (entityOpt.isPresent()) { // 根据订单号查询订单, 若订单已经存在, 则更新订单内容
                orderEntity.setId(entityOpt.get().getId());
                updateList.add(orderEntity);
            } else {
                insertList.add(orderEntity);
            }

            calculateOrderIncomeAndAgentId(orderEntity, domainId);
        }

        Map<String, Integer> result = new HashMap<>();
//        List<OrderEntity> resultList = orderV2Repository.saveAll(orderEntityList);

        int insert = orderV2Repository.saveAll(insertList, domain);
        int update = orderV2Repository.updateAll(updateList, domain);
        result.put("total", insert + update);
        result.put("update", update);
        result.put("insert", insert);
        return result;
    }


    // 设置 订单对于的 代理Id 以及对于的收入
    private void calculateOrderIncomeAndAgentId(OrderEntity orderEntity, final Long domainId) {
        Map<String, Object> config = globalConfigService.queryConfig(domainId);
        Double orderIncome = orderEntity.getEstimatedIncome() == null ? orderEntity.getEstimatedIncome() : orderEntity.getEffectPrediction();
        Double alimamaServicePercent = Double.parseDouble(config.get(Constants.SERVICE_FEE_RATIO).toString());
        Double income = orderIncome * (100 - alimamaServicePercent) / 100; // 扣除阿里妈妈的服务费

        String pid = orderEntity.getPid();
        if (pid == null) {
            // done PID 为空, 则当成管理的推广处理。
            // 管理员订单
            orderEntity.setAdminAmount(income);
            return;
        }
        val agentEntityOpt = agentRepository.findByPid(pid, domainId);

        // 管理员订单
        if (! agentEntityOpt.isPresent()) {
            // 管理员自己推广的
            orderEntity.setAdminAmount(income);
            return;
        }

        AgentEntity agentEntity = agentEntityOpt.get();
        Double promoterIncome = income * agentEntity.getPerOfCommission() / 100;
        Double parentIncome = 0.0;
        Double grandParentIncome = 0.0;

        if (agentEntity.getParentId() != null && agentEntity.getParentPerOfCommission() != null) {
            parentIncome = income * agentEntity.getParentPerOfCommission() / 100;
        }
        if (agentEntity.getGrandParentId() != null && agentEntity.getGrandParentPerOfCommission() != null) {
            grandParentIncome = income * agentEntity.getGrandParentPerOfCommission() / 100;
        }
        orderEntity.setParentAmount(parentIncome);
        orderEntity.setGrandParentAmount(grandParentIncome);
        orderEntity.setPromoterAmount(promoterIncome);

        // 管理员等于剩余分佣之后的账本
        Double adminIncome = income - promoterIncome - parentIncome - grandParentIncome;
        orderEntity.setAdminAmount(adminIncome);

        orderEntity.setGrandParentId(agentEntity.getGrandParentId());
        orderEntity.setParentId(agentEntity.getParentId());
        orderEntity.setPromoterId(agentEntity.getId());

        logger.debug("save order => {}", GsonUtil.getJsonString(orderEntity));
    }

    /**
     * 管理员分页查询所有订单
     *
     * @param pageable
     * @return
     */
    public Page<OrderEntity> searchOrderPagingForAdmin(String keyword, Pageable pageable, final Long domainId, final String domain) {
        keyword = keyword == null ? "" : keyword;

        Page<OrderEntity> orderPage = orderV2Repository.findOrdersByKeyword(keyword, domain, pageable);

        // 给order设置代理信息
        // orderPage.forEach(orderEntity -> agentRepository.findByPid(orderEntity.getPid(), domainId).ifPresent(agentEntity -> orderEntity.setAgent(agentEntity)));
        for(OrderEntity order : orderPage) {
            Optional<AgentEntity> entityOptional = agentRepository.findByPid(order.getPid(), domainId);
            entityOptional.ifPresent(e -> order.setAgent(e));
        }

        return orderPage;
    }

    /**
     * 代理分页查询所有订单
     *
     * @param pageable
     * @return
     * @Param agentEntity
     */
    public Page<OrderEntity> getOrderPagingForAgent(Long agentId, String keyword, Pageable pageable, final Long domainId, final String domain) {
        keyword = keyword == null ? "" : keyword;
        Page<OrderEntity> orderPage = orderV2Repository.findOrdersForAgentByKeyword(agentId, keyword, domain, pageable);

        // 给order设置代理信息
        // orderPage.forEach(order -> order.setAgent(agentRepository.findByPid(order.getPid(), domainId).get()));
        for (OrderEntity order : orderPage) {
            Optional<AgentEntity> entityOptional = agentRepository.findByPid(order.getPid(), domainId);
            entityOptional.ifPresent(e -> order.setAgent(e));
        }

        return orderPage;
    }


//    private final @NonNull OrderRepository orderRepository;

    private final @NonNull OrderV2Repository orderV2Repository;

    private final @NonNull AgentRepository agentRepository;

    private final @NonNull GlobalConfigService globalConfigService;

    private final @NonNull PIDRepository pidRepository;

    private static Logger logger = LogManager.getLogger(OrderService.class);
}
